package cc.ttiot.service.dataTransmission.mqtt;

import cc.ttiot.mapper.dto.Picture;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import static cc.ttiot.enums.SystemConstant.*;
import static cc.ttiot.utils.JavaBase64Utils.decode;

/**
 * @Description: 用于保存MQTT客户端信息
 * 在主程序解决异常，这里仅仅抛出
 * @Author :
 * @Version :
 * @Date :
 */

//纯测试使用
public class Client1 {
    private static volatile Client1 client;

    /**
     * @field user          连接MQTT服务器的用户名
     * @field password      连接MQTT服务器的密码
     * @field clientID      MQTT客户端的唯一标识符（不能与该服务器下其他客户端的clientID重复）
     * @field mqttClient    MQTT客户端
     */
    private final String userName;
    private final String password;
    private final String clientID = "woainiya";
    private final String broker;

    private MqttClient mqttClient;
    private final MqttConnectOptions connOpts;
    private int i = 1;
    private int j = 1;

    {
        //赋值
        userName = MQTT_USER_NAME;
        password = MQTT_PASSWORD;
        broker = BROKER;

        // 内存存储
        MemoryPersistence persistence = new MemoryPersistence();
        // 创建客户端
        try {
            mqttClient = new MqttClient(broker, clientID, persistence);
        } catch (MqttException e) {
            e.printStackTrace();
        }
        // 创建链接参数
        connOpts = new MqttConnectOptions();
        // 设置连接的用户名
        connOpts.setUserName(userName);
        connOpts.setPassword(password.toCharArray());
        // 设置超时时间，单位为秒
//        connOpts.setConnectionTimeout(1000);
        // 在重新启动和重新连接时记住状态
        connOpts.setCleanSession(true);
    }

    //构造函数
    private Client1() {
        super();
    }

    //获取Client对象
    public static Client1 getInstance() {
        if (client == null) {
            synchronized (Client1.class) {
                if (client == null) {
                    client = new Client1();
                }
            }
        }
        return client;
    }

    //提供mqttClient的get方法
    public MqttClient getMqttClient() {
        return mqttClient;
    }

    //判断是否连接
    public boolean isConnected() {
        return mqttClient.isConnected();
    }

    //创建与MQTT服务器的连接
    public void createConnection() throws MqttException {
        // 建立连接
        mqttClient.connect(connOpts);
    }

    //关闭与MQTT服务器的连接
    public void closeConnection() throws MqttException {
        // 断开连接
        mqttClient.disconnect();
    }

    //关闭客户端(不要调用该方法)
    public void closeClient() throws MqttException {
        // 关闭客户端
        mqttClient.close();
    }

    //发布消息
    public void publishMessage(String topic, String message) throws MqttException {
        // 创建消息
        MqttMessage mqttMessage = new MqttMessage(message.getBytes());
        // 发布消息
        mqttClient.publish(topic, mqttMessage);
    }

    public void publishMessage(String topic, String message, int qos) throws MqttException {
        // 创建消息
        MqttMessage mqttMessage = new MqttMessage(message.getBytes());
        // 设置消息的服务质量
        mqttMessage.setQos(qos);
        // 发布消息
        mqttClient.publish(topic, mqttMessage);
    }

    //订阅消息(打印)
    public void subscribeMessage(String topic) throws MqttException {
        // 设置回调函数
        mqttClient.setCallback(new MqttCallback() {

            public void connectionLost(Throwable cause) {//当mosquito服务器挂了之后，就爆出这个信息
                System.out.println("connectionLost");
            }

            //收到消息时调用该方法
            public void messageArrived(String topic, MqttMessage message) throws Exception {
                String mes = new String(message.getPayload());
                System.out.println("收到来自 " + topic + " 主题的消息！");
                System.out.println("采集到的数据为 " + mes);
            }

            public void deliveryComplete(IMqttDeliveryToken token) {
                System.out.println("deliveryComplete---------" + token.isComplete());
            }

        });
        mqttClient.subscribe(topic);
    }

    //https://www.jianshu.com/p/fb35dbf6b601
    public void subscribeMessage(String topic, int qos) throws MqttException {
        // 设置回调函数
        mqttClient.setCallback(new MqttCallback() {

            public void connectionLost(Throwable cause) {
                System.out.println("connectionLost");
            }

            //收到消息时调用该方法
            public void messageArrived(String topic, MqttMessage message) throws MqttException {
                String mes = new String(message.getPayload());
                System.out.println("收到来自 " + topic + " 主题的消息！");
                System.out.println("采集到的数据为 " + mes);

                if (topic.equals("Camera")) {

                    JSONObject jsonObject = JSON.parseObject(mes);
                    String picture = jsonObject.getString("msg");
                    System.out.println("doorId" + jsonObject.getLong("doorId"));
                    if (jsonObject.getLong("doorId") == 4521260549669376L) {
                        JSONObject jo = JSONObject.parseObject(picture);
                        Picture picture1 = JSON.toJavaObject(jo, Picture.class);

                        //二进制转化为图片
                        if (j > 1000) {
                            j = 1;
                        }

                        try (FileOutputStream fileOutputStream = new FileOutputStream(new File("C:\\Users\\WangSuheng\\Desktop\\te1\\" + j + ".png"));) {
                            fileOutputStream.write(decode(picture1.getPicture().getBytes()));
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        j++;
                    }else{
                        JSONObject jo = JSONObject.parseObject(picture);
                        Picture picture1 = JSON.toJavaObject(jo, Picture.class);

                        //二进制转化为图片
                        if (i > 1000) {
                            i = 1;
                        }

                        try (FileOutputStream fileOutputStream = new FileOutputStream(new File("C:\\Users\\WangSuheng\\Desktop\\te\\" + i + ".png"));) {
                            fileOutputStream.write(decode(picture1.getPicture().getBytes()));
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        i++;
                    }

                }
            }

            public void deliveryComplete(IMqttDeliveryToken token) {
                System.out.println("deliveryComplete---------" + token.isComplete());
            }

        });
        mqttClient.subscribe(topic, qos);
    }

    //创建与MQTT服务器的连接（发布）
    public void createConnection4Publish() throws MqttException {

        // 内存存储
        MemoryPersistence persistence = new MemoryPersistence();
        // 创建客户端
        MqttClient mqttClient = new MqttClient(broker, clientID, persistence);
        this.mqttClient = mqttClient;
        // 创建链接参数
        MqttConnectOptions connOpts = new MqttConnectOptions();
        // 在重新启动和重新连接时记住状态
        connOpts.setCleanSession(false);
        // 设置连接的用户名
        connOpts.setUserName(userName);
        connOpts.setPassword(password.toCharArray());
        // 建立连接
        mqttClient.connect(connOpts);

    }

    //创建与MQTT服务器的连接（订阅）
    public void createConnection4Subscribe() throws MqttException {

        // 内存存储
        MemoryPersistence persistence = new MemoryPersistence();
        // 创建客户端
        MqttClient mqttClient = new MqttClient(broker, clientID, persistence);
        this.mqttClient = mqttClient;
        // 创建链接参数
        MqttConnectOptions connOpts = new MqttConnectOptions();
        // 在重新启动和重新连接时记住状态
        connOpts.setCleanSession(false);
        // 设置连接的用户名
        connOpts.setUserName(userName);
        connOpts.setPassword(password.toCharArray());
        // 设置超时时间，单位为秒
        connOpts.setConnectionTimeout(1000);
        // 设置会话心跳时间，单位为秒，服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线，但这个方法并没有重连的机制
        connOpts.setKeepAliveInterval(1000);
        // 建立连接
        mqttClient.connect(connOpts);
    }

}
